Skip to content

TCK tests for async invokers#706

Open
Ladicek wants to merge 7 commits into
jakartaee:mainfrom
Ladicek:async-invokers
Open

TCK tests for async invokers#706
Ladicek wants to merge 7 commits into
jakartaee:mainfrom
Ladicek:async-invokers

Conversation

@Ladicek
Copy link
Copy Markdown
Member

@Ladicek Ladicek commented Apr 13, 2026

Fixes #698

@Ladicek Ladicek added this to the CDI 5.0 milestone Apr 13, 2026
@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented Apr 13, 2026

Draft because the TCK audit already contains changes from jakartaee/cdi#961. Otherwise this is ready for review and then merge.

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented Apr 16, 2026

Rebased. Since jakartaee/cdi#961 was merged, this is ready for review.

@Ladicek Ladicek marked this pull request as ready for review April 16, 2026 11:43
@manovotn manovotn requested review from Azquelt and manovotn April 16, 2026 13:51
Copy link
Copy Markdown
Contributor

@manovotn manovotn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add a test for AfterDeploymentValidation.ensureAsyncHandlerExists()

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented Apr 20, 2026

We should also add a test for AfterDeploymentValidation.ensureAsyncHandlerExists()

If anything, we should add a copy of this PR for Portable Extensions. I don't see the need to add a test for this one method, without testing the rest of the infrastructure through PEs.

@manovotn
Copy link
Copy Markdown
Contributor

We should also add a test for AfterDeploymentValidation.ensureAsyncHandlerExists()

If anything, we should add a copy of this PR for Portable Extensions. I don't see the need to add a test for this one method, without testing the rest of the infrastructure through PEs.

That would be even better for sure :)

@manovotn
Copy link
Copy Markdown
Contributor

@Ladicek do you want to address the PE counterpart in this PR should we open a new one?
Because as far as BCEs are concerned, I am happy with this PR.

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented Apr 20, 2026

To be honest, I'd love someone else to do the PE part 😆

@manovotn
Copy link
Copy Markdown
Contributor

manovotn commented Apr 20, 2026

To be honest, I'd love someone else to do the PE part 😆

I have added a PE variant of the three positive test cases - is that OK with you @Ladicek?

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented Apr 21, 2026

Just about perfect, thanks!

Copy link
Copy Markdown
Contributor

@manovotn manovotn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented Apr 27, 2026

Added a 2nd commit that contains TCK tests for the respecified async handlers (jakartaee/cdi#967). Before merging, the commits should be squashed.

Asked for a new review.

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented Apr 29, 2026

@manovotn I think I screwed up by force-pushing the new TCK, because that dropped your commit with PEs tests. Do you by any chance still have them locally? Thanks! :-)

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented May 4, 2026

Squashed and rebased.

@manovotn could you please take a look if you still have your PE tests locally? Sorry I dropped them.

@manovotn
Copy link
Copy Markdown
Contributor

manovotn commented May 4, 2026

Squashed and rebased.

@manovotn could you please take a look if you still have your PE tests locally? Sorry I dropped them.

Pushed

Copy link
Copy Markdown
Contributor

@manovotn manovotn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went over the tests as I was implementing it in Weld and it LGTM 👍

@manovotn
Copy link
Copy Markdown
Contributor

@Azquelt if you get a chance, could you please review this PR as well as #709?
I was holding these off until you get a chance to take a look.

Afterwards, I would love to work towards releasing Beta versions of both, CDI and TCKs; as per the release timeline for Jakarta, M4 is nearing.

@Azquelt
Copy link
Copy Markdown
Member

Azquelt commented May 12, 2026

Yeah, I will take a look

Copy link
Copy Markdown
Member

@Azquelt Azquelt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that some of the spec assertions are out of date and need fixed.

I also realised that with a parameter async handler the dependent beans may be destroyed before the method returns and I'm not sure if that's the behaviour we want (though that's a spec issue, not really related to these tests)


@Test
@SpecAssertion(section = Sections.USING_INVOKER_BUILDER_FULL, id = "a")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "ja")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ja should be la


@Test
@SpecAssertion(section = Sections.USING_INVOKER_BUILDER_FULL, id = "a")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "jb")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jb should be lb


@Test
@SpecAssertion(section = Sections.USING_INVOKER_BUILDER_FULL, id = "a")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "jc")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jc should be lc

Comment on lines +80 to +82
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "b")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "g")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "h")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be cf, hb, j I think?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf, hb, i, j actually

Comment on lines +109 to +111
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "b")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "i")
public void testSyncThrow() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf and hc?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ha (synchronous completion) appears not to be tested in PE and neither is the transformReturnValue method.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf and hc?

cf, hc, k actually

ha (synchronous completion) appears not to be tested in PE

Correct. I'm adding a test, because there's one for BCE.

and neither is the transformReturnValue method.

Need to take a look at this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and neither is the transformReturnValue method.

Need to take a look at this.

This is actually more widespread: we don't have any test that would check transformReturnValue(). I'll try to add one (or two, actually -- for BCE and PE).

Comment on lines +80 to +83
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "b")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "g")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "h")
public void test() throws Exception {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be, gb and j

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be, gb, i, j actually

Comment on lines +110 to +112
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "b")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "i")
public void testSyncThrow() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be, gc and k

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A test for synchronous successful completion is missing here too, and I'm also adding it.

Comment on lines +75 to +93
@Test(dataProvider = ARQUILLIAN_DATA_PROVIDER)
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "cf")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "ha")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "i")
@SpecAssertion(section = Sections.INVOKER_ASYNCHRONOUS_METHODS, id = "j")
public void testSync(InvokerHolder invokers) throws Exception {
MyDependentBean.reset();

Invoker<MyBean, MyAsyncType<String>> hello = invokers.get("helloSync");
MyAsyncType<String> result = MyAsyncType.createSuspended();

assertEquals(MyDependentBean.destroyedCounter.get(), 0);

hello.invoke(null, new Object[] { null, result });

assertEquals(MyDependentBean.destroyedCounter.get(), 1);
assertTrue(result.isComplete());
assertEquals(result.getIfComplete(), "hello");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this test we don't assert whether the dependent beans are destroyed before or after the method returns.

I think that, as currently specified, the beans should be destroyed as soon as async.resume is called inside the helloSync method, i.e. before the method returns, which is a little odd given that you could be destroying the bean that you called the method on and it's a bit difficult for the async handler to avoid that.

As the spec is currently written, I think this test is correct but we might want to consider deferring destruction until both complete is called and the method returns.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good observation! Let me think about that for a bit.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I addressed all comments except of this one. It is a little tricky.

Currently, the specification indeed requires that completion is signaled and hence CC is released before the method returns. This would be especially wrong if the target bean is @Dependent and its instance is looked up by the invoker.

I tried fixing the issue locally and there seems to be a relatively straightforward way, so I'll look at:

  1. specifying that the CC is released after the method returns, even if completion was signaled before the method returned,
  2. modifying the TCK.

Hopefully tomorrow.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitted a spec clarification: jakartaee/cdi#973

Will submit fixed tests to this PR later today.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added one commit with a test. Turns out it's just one assert in an existing test, which seems nice :-)

manovotn and others added 4 commits May 13, 2026 13:32
A "two-way" async type signals completion through two different ways:

- synchronous completion is signalled through the method's return value
- asynchronous completion is signalled through the async parameter
  and the return value is a dummy placeholder

This occurs in practice with Kotlin `suspend` functions, where if
the function completes synchronously, it returns the value directly,
and if it completes asynchronously, it signals completion through
a parameter (and the return value is a placeholder).

The tests in this commit are of course not written in Kotlin, but
they are structured in the same way.
These tests ignore the return values of invokers, so the wrong return type
has not been an issue. It is still wrong, though, and should be fixed.
@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented May 13, 2026

Rebased and added 3 commits:

  • update Portable Extensions tests, should be squashed before merging
    • fixes assertion IDs as reported by @Azquelt
  • add tests for async handlers of "two-way" async types
    • adds missing tests that exercise transformReturnValue()
  • fix invoker return types in some tests
    • fixes wrong Invoker return types; these were not used, so were not caught, but are wrong anyway and so should be fixed

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented May 14, 2026

This PR now includes a test of jakartaee/cdi#973

@Ladicek
Copy link
Copy Markdown
Member Author

Ladicek commented May 15, 2026

I intend to squash the commits here before merging, but will leave the PR in its current state for easier review.

@manovotn manovotn requested a review from Azquelt May 15, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create TCK coverage for async invokers

3 participants